package pl.wroc.uni.ii.puzzle.game;

import java.util.ArrayList;
import java.util.Random;

import android.graphics.Canvas;
import android.graphics.Color;

public class PlayBoard extends Board {

	private int rows;
	private int columns;
	private int cellWidth;
	private int cellHeight;
	private Cell selectedCell = null;
	
	private ArrayList<Cell> cells;

	public PlayBoard(Game game, int level, int screenWidth, int screenHeight, String hardship) {
		super(game, level);
		setHardship(hardship);
		cellWidth = screenWidth / columns;
		cellHeight = screenHeight / rows;
		createAndInitCells();
	}
	
	private void setHardship(String hardship) {
		if ("Easy".equals(hardship)) {
			rows = Game.ROWS_COUNT_EASY;
			columns = Game.COLUMNS_COUNT_EASY;		
		}
		else if ("Medium".equals(hardship)) {
			rows = Game.ROWS_COUNT_MEDIUM;
			columns = Game.COLUMNS_COUNT_MEDIUM;		
		}
		else  { //"Hard"
			rows = Game.ROWS_COUNT_HARD;
			columns = Game.COLUMNS_COUNT_HARD;		
		}
	}

	private void createAndInitCells() {
		cells = new ArrayList<Cell>(rows*columns);
		for (int i=0; i<rows; i++) {
			for (int j=0; j<columns; j++) {
				Cell cell = new Cell(i,j,cellWidth,cellHeight,bitmap);
				cells.add(cell);
			}
		}
		mixCells();
	}

	@Override
	public void draw(Canvas canvas) {
		canvas.drawColor(Color.BLACK);
		drawCells(canvas);
	}
	
	private void drawCells(Canvas canvas) {
		for (Cell cell : cells) {
			cell.draw(canvas);
		}
	}

	private Cell getCellFromCoordinates(float x, float y) {
		int row = (int)y / cellHeight;
		int column = (int)x / cellWidth;
		
		if (row>=rows || column>=columns) {
			return null;
		}
		int position = row * columns + column;
		return cells.get(position);
	}
	
	private void selectCell(Cell c) {
		notifyUserWithSound();

		c.switchSelection();
		
		if (isFirstSelected(c)) {
			selectedCell = c;
		}
		if (isSecondSelected(c)) {
			swapCellsPositionsAndNotify(selectedCell, c);
			selectedCell = null;
		}
		if (isUnSelected(c)) {
			selectedCell = null;
		}
	}

	public void swapCellsPositionsAndNotify(Cell c1, Cell c2) {
		swapCellsPositions(c1, c2);
		c1.switchSelection();
		c2.switchSelection();
		notifyUserWithVibration();
	}

	@Override
	public void refreshState() {
		if (isLevelCompleted()) {
			game.startNewLevel();
		}
	}

	private void swapCellsPositions(Cell c1, Cell c2) {
		c1.swapPostionWithCell(c2);
	}
	
	private void notifyUserWithVibration() {
		game.vibrate(Game.DURATION_OF_VIBRATE_NOTIFICATION);
	}
	
	private void notifyUserWithSound() {
		game.playSound(Game.CLICK_SOUND_ID);
	}
	
	private void mixCells() {
		int cellCount = rows*columns;
		Random random = new Random();
		Cell c1;
		Cell c2;
		for (int i=0; i<100; i++) {
			c1 = cells.get(random.nextInt(cellCount));
			c2 = cells.get(random.nextInt(cellCount));
			swapCellsPositions(c1, c2);
		}
		
		c1 = cells.get(1);
		c2 = cells.get(3);
		swapCellsPositions(c1, c2);
	}
	
	private boolean isLevelCompleted() {
		for (Cell c : cells) {
			if (!c.isInProperPosition()) {
				return false;
			}
		}
		return true;
	}	

	private boolean isSecondSelected(Cell c) {
		return (c != selectedCell && c.isSelected());
	}

	private boolean isUnSelected(Cell c) {
		return (c == selectedCell && !c.isSelected());
	}

	private boolean isFirstSelected(Cell c) {
		return (selectedCell == null && c.isSelected());
	}
	
	@Override
	public void clickCellFromCoordinates(float x, float y) {
		Cell c = getCellFromCoordinates(x, y);
		if (c!= null) {
			selectCell(c);
		}
	}

	@Override
	public void swipeBottomToTopCellFromCoordinates(float x, float y) {
		Cell c = getCellFromCoordinates(x, y);
		if (c!= null) {
			c.reflectVertical();
		}
	}
	
	@Override
	public void swipeTopToBottomCellFromCoordinates(float x, float y) {
		Cell c = getCellFromCoordinates(x, y);
		if (c!= null) {
			c.reflectVertical();
		}
	}

	@Override
	public void swipeLeftToRightCellFromCoordinates(float x, float y) {
		Cell c = getCellFromCoordinates(x, y);
		if (c!= null) {
			c.reflectHorizontal();
		}
	}

	@Override
	public void swipeRightToLeftCellFromCoordinates(float x, float y) {
		Cell c = getCellFromCoordinates(x, y);
		if (c!= null) {
			c.reflectHorizontal();
		}
	}
}
